package 多线程.Test;


import java.util.concurrent.Semaphore;
/*
* 信号量Semaphore的实现
Semaphore（信号量）是用来控制同时访问特定资源的线程数量，
* 它通过协调各个线程，以保证合理的使用公共资源，在操作系统中是一个非常重要的问题，用来解决哲学家就餐问题。

Java中的Semaphore维护了一个许可集，一开始先设定这个许可集的数量，
* 可以使用acquire()方法获得一个许可，当许可不足时会被阻塞，release()添加一个许可。

在下列代码中，还加入了另外一个mutex信号量，维护生产者消费者之间的同步关系，
* 保证生产者和消费者之间的交替进行
*/
public class SemaphoreTest {

    private static int count = 0;

    //创建三个信号量
    private final Semaphore notFull = new Semaphore(10);
    private final Semaphore notEmpty = new Semaphore(0);
    private final Semaphore mutex = new Semaphore(1);


    class Producer implements Runnable {

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    notFull.acquire();//获取许可
                    mutex.acquire();
                    count++;
                    System.out.println(Thread.currentThread().getName() + "-生产者生产，数量为:" + count);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    mutex.release();//释放
                    notEmpty.release();
                }
            }
        }
    }

    class Consumer implements Runnable {

        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                try {
                    notEmpty.acquire();
                    mutex.acquire();
                    count--;
                    System.out.println(Thread.currentThread().getName() + "-消费者消费，数量为："+ count);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    mutex.release();
                    notFull.release();
                }
            }
        }
    }

    public static void main(String[] args) {
        SemaphoreTest semaphoreTest = new SemaphoreTest();
        new Thread(semaphoreTest.new Producer()).start();
        new Thread(semaphoreTest.new Consumer()).start();
        new Thread(semaphoreTest.new Producer()).start();
        new Thread(semaphoreTest.new Consumer()).start();
        new Thread(semaphoreTest.new Producer()).start();
        new Thread(semaphoreTest.new Consumer()).start();
    }
}

